﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using EITSurferInfinityLib;

namespace ControlerLib
{
    /// <summary>
    /// Interaction logic for SimpleGraph.xaml
    /// </summary>
    public partial class SimpleGraph : UserControl
    {

        int ReferenceIndex;
        int CurrentDataIndex;
        Canvas Ref;
        Canvas Cur;
        Canvas Phantom;

        string LastPressed;

        bool IsDragging;
        double PhantomPositionX;
        double RefPositionX;
        double CurPositionX;
        double CursorWidth;

        bool FirstClick;

        public List<double> data;

        public delegate void NewReferenceSelectedEventHandler(object sender, EventArgsSimpleGraph e);
        public delegate void NewCurrentSelectedEventHandler(object sender, EventArgsSimpleGraph e);
        public event NewReferenceSelectedEventHandler OnNewReferenceSelected;
        public event NewCurrentSelectedEventHandler OnNewCurrentSelected;  
        
        public SimpleGraph()
        {
            InitializeComponent();
            data = new List<double>();
            data.Add(1.2);
            data.Add(-1.2);
            data.Add(-1.2);
            data.Add(10.2);
            data.Add(1.2);
            ReferenceIndex = 0;
            CurrentDataIndex = 0;
            Ref = new Canvas();
            Cur = new Canvas();
            Phantom = new Canvas();
            ResetMouse();

            //Ref.MouseMove += new MouseEventHandler(dz_MouseMove);
            //Cur.MouseMove += new MouseEventHandler(dz_MouseMove);

            PhantomPositionX=0;
            RefPositionX = 0;
            CurPositionX=0;
            CursorWidth=10;

            dz.MouseMove += new MouseEventHandler(dz_MouseMove);
            this.MouseEnter += new MouseEventHandler(SimpleGraph_MouseEnter);
            this.MouseLeave += new MouseEventHandler(SimpleGraph_MouseLeave);
        }





        #region external events
            protected virtual void NewReferenceSelected(EventArgsSimpleGraph e)
        {
            if (OnNewReferenceSelected != null)
                OnNewReferenceSelected(this, e);
        }
            protected virtual void NewCurrentSelected(EventArgsSimpleGraph e)
        {
            if (OnNewCurrentSelected != null)
                OnNewCurrentSelected(this, e);
        }
        #endregion

        #region internal events
            private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Update();
        }
            private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            Update();
        }
        #endregion

        #region MouseInteraction
            void SimpleGraph_MouseLeave(object sender, MouseEventArgs e)
            {
                ResetMouse();
            }
            void SimpleGraph_MouseEnter(object sender, MouseEventArgs e)
            {
                ResetMouse();
            }
            void r_MouseUp(object sender, MouseButtonEventArgs e)
            {
                if (e.LeftButton == MouseButtonState.Released)
                {
                    IsDragging = false;
                    if (LastPressed == "Ref")
                    {
                        ReferenceIndex = CalculateHorizontalIndex(e.GetPosition(dz).X);
                        EventArgsSimpleGraph eRef = new EventArgsSimpleGraph();
                        eRef.index = ReferenceIndex;
                        NewReferenceSelected(eRef);
                    }
                    if (LastPressed == "Cur")
                    {
                        CurrentDataIndex = CalculateHorizontalIndex(e.GetPosition(dz).X);
                        EventArgsSimpleGraph eCur = new EventArgsSimpleGraph();
                        eCur.index = CurrentDataIndex;
                        NewCurrentSelected(eCur);
                    }
                    FirstClick = false;
                    LastPressed = "";
                    Update();
                }
            }
            void dz_MouseMove(object sender, MouseEventArgs e)
            {
                if (Ref.IsMouseOver)
                {
                    this.Cursor = Cursors.SizeWE;
                }
                else if (Cur.IsMouseOver)
                {
                    this.Cursor = Cursors.SizeWE;
                }
                else
                {
                    this.Cursor = Cursors.Arrow;
                }

                if (e.LeftButton == MouseButtonState.Pressed)
                {
                    if (FirstClick == false)
                    {
                        FirstClick = true;
                        if ((e.GetPosition(dz).X >= RefPositionX) && (e.GetPosition(dz).X <= RefPositionX + CursorWidth))
                        {
                            LastPressed = "Ref";
                        }
                        if ((e.GetPosition(dz).X >= CurPositionX) && (e.GetPosition(dz).X <= CurPositionX + CursorWidth))
                        {
                            LastPressed = "Cur";
                        }
                    }
                    PhantomPositionX = e.GetPosition(dz).X-(CursorWidth / 2);
                    IsDragging = true;
                    Update();
                }
                else if (e.LeftButton == MouseButtonState.Released)
                {
                    ResetMouse();
                }
            }
        #endregion

        #region Draw Graph and Cursors
            private int CalculateHorizontalIndex(double x)
        {

            double h = dz.ActualHeight;
            double w = dz.ActualWidth;

            int index=0;

            if (w != 0)
            {
                 index=(int)Math.Round(x *data.Count/w);
            }
            else
            {
                
            }
            return index;
        }
            private void DrawCursor(ref Canvas c, double x, Brush b)
            {
                if ((x < 0) || (double.IsNaN(x)))
                {
                    x=0;
                }

                double h = dz.ActualHeight;

                Rectangle r = new Rectangle()
                {
                    Width = CursorWidth,
                    Height = h,
                    Visibility = System.Windows.Visibility.Visible,
                    Margin = new Thickness(x, 0, 0, 0),
                    StrokeThickness = 0,
                    Stroke = System.Windows.Media.Brushes.Black,
                    Fill = b
                };

                r.MouseUp += new MouseButtonEventHandler(r_MouseUp);
                c.Children.Add(r);  
            }
            private void DrawReference()
            {
                Ref.Children.Clear();
                RefPositionX = (dz.ActualWidth / data.Count) * ReferenceIndex - (CursorWidth / 2);
                DrawCursor(ref Ref, RefPositionX, Brushes.GreenYellow);
                
                dz.Children.Add(Ref);
            }
            private void DrawCurrent()
            {
                Cur.Children.Clear();
                CurPositionX = (dz.ActualWidth / data.Count) * CurrentDataIndex - (CursorWidth / 2);
                DrawCursor(ref Cur, CurPositionX, Brushes.Red);
                dz.Children.Add(Cur);
            }
            private void DrawPhantom(Brush b)
            {
                Phantom.Children.Clear();
                DrawCursor(ref Phantom, PhantomPositionX, b);
                //CurPositionX = (dz.ActualWidth / data.Count) * CurrentDataIndex;
                dz.Children.Add(Phantom);
            }
            private void Clear()
            {
                data.Clear();
            }
            private double [] GetMinMax()
        {
            double [] result = new double [2];
            if (data.Count > 0)
            {
                double min = data[0];
                double max = data[0];
                for (int i = 0; i < data.Count; i++)
                {
                    if (min > data[i])
                    {
                        min = data[i];
                    }
                    if (max < data[i])
                    {
                        max = data[i];
                    }
                }
                result[0] = min;
                result[1] = max;
            }
            return result;
        }
            private void DrawGraph()
            {
            double h = dz.ActualHeight;
            double w = dz.ActualWidth;
            double [] minmax=GetMinMax();
            double dataMin = minmax[0];
            double dataMax = minmax[1];
            double dataLength = data.Count;

            double[] dataY = new double[data.Count];
            double[] dataX = new double[data.Count];

            if (h != 0)
            {
                for (int i = 0; i < data.Count; i++)
                {
                    dataX[i] = (w / dataLength) * i;
                    dataY[i] = h-(h/(dataMax - dataMin) * (data[i]-dataMin));
                }
            }

            

            Line line;
            Thickness thickness;
            for (int i = 0; i < dataLength - 1;i++ )
            {

                if ((dataY[i] != double.NaN)&&(dataY[i+1] != double.NaN))
                {
                    line = new Line();
                    thickness = new Thickness(0, 0, 3, 3);
                    line.Margin = thickness;
                    line.Visibility = System.Windows.Visibility.Visible;
                    line.StrokeThickness = 1;
                    line.Stroke = System.Windows.Media.Brushes.Black;
                    line.X1 = dataX[i];
                    line.X2 = dataX[i + 1];
                    line.Y1 = dataY[i];
                    line.Y2 = dataY[i + 1];
                    dz.Children.Add(line);
                }
            }
           
        }
        #endregion

        #region public methods
            public void ResetMouse()
            {
                FirstClick = false;
                IsDragging = false;
                LastPressed = "";
            }
            public void Update()
            {
                dz.Children.Clear();

                DrawGraph();
                DrawCurrent();
                DrawReference();

                if (IsDragging)
                {
                    if (LastPressed == "Ref")
                    {
                        DrawPhantom(System.Windows.Media.Brushes.LightGreen);
                        //DrawCursor(ref dz, PhantomPositionX, System.Windows.Media.Brushes.LightGreen);
                    }
                    if (LastPressed == "Cur")
                    {
                        DrawPhantom(System.Windows.Media.Brushes.LightPink);
                        //DrawCursor(ref dz, PhantomPositionX, System.Windows.Media.Brushes.LightPink);
                    }
                }
            }

            public void SetReference()
            {
                ReferenceIndex = data.Count;
            }
            public void SetCurrent()
            {
                CurrentDataIndex = data.Count;
            }
            public void SetCurrent(int index)
            {
                CurrentDataIndex = index;
            }
            public void SetCurrentPlusOne()
            {
                CurrentDataIndex++;
            }
            public void UpdateHistory(ref List<double> d)
            {
                for (int i = 1; i < d.Count - 1; i++)
                {
                    if(i>data.Count)
                    {
                        data.Add(d[i-1]);
                    }
                    //else if(i<=data.Count)
                    //{
                    //        data[i-1]=d[i-1];  //
                    //}
                }
            }
        #endregion
    }
}
